package com.xh.baselibrary.utils

import android.os.SystemClock
import com.xh.baselibrary.log.XLog
import java.util.*

/**
 * 超时通知Unit
 */
open class Timeout(private val time: Long = DEFAULT_TIME) : Comparable<Timeout> {
    private var addQueueTime: Long = 0
    private var id = 0L
    private var updateTime = time
    open fun timeout() {
        XLog.i("timeout()--->$this")
    }

    override fun toString(): String {
        return "id--->$id, times--->$time, updateTime--->$updateTime , currTime--->$addQueueTime"
    }

    override fun compareTo(other: Timeout): Int {
        val otherTime = other.addQueueTime + other.time
        val thisTime = this.addQueueTime + this.time
        val timeCount = thisTime - otherTime
        return timeCount.toInt()
    }

    companion object {
        const val DEFAULT_TIME = TimeUnit.SECOND * 15
        const val DEFAULT_WAIT_TIME = TimeUnit.SECOND * 20
        const val TAG = "TimeoutTimer"
        private var timeoutTimer: TimeoutTimer? = null
        private var timeoutID = 0L
        @JvmStatic
        fun start() {
            if (timeoutTimer == null) {
                timeoutTimer = TimeoutTimer()
                timeoutTimer!!.start()
            }
        }
        @JvmStatic
        fun stop() {
            if (timeoutTimer != null) {
                timeoutTimer!!.interrupt()
            }
            timeoutTimer = null
        }
        @JvmStatic
        fun scheduleTimeout(node: Timeout) {
            node.id = timeoutID++
            timeoutTimer?.addTimeout(node)
        }
        @JvmStatic
        fun removeTimeout(node: Timeout):Boolean {
            if(timeoutTimer == null){
                return false
            }
            return timeoutTimer!!.removeNode(node)
        }

    }

    class TimeoutTimer : Thread() {
        private val lock = Object()
        private var isRunning = false
        private val timeoutList = LinkedList<Timeout>()
        override fun start() {
            isRunning = true
            super.start()
        }

        override fun interrupt() {
            isRunning = false
            super.interrupt()
        }
        override fun run() {
            while (isRunning) {
                try {
                    val timeout: Timeout = awaitTimeout() ?: continue
                    timeout.timeout()
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }
            XLog.i("TimeoutTimer finished--->")
        }

        fun removeNode(node: Timeout):Boolean {
            synchronized(lock) {
                val index = timeoutList.indexOf(node)
                val removed = timeoutList.remove(node)
                if(removed){
                    XLog.i("removeNode--->$node")
                }
                if (index == 0) {
                    lock.notify()
                }
                return removed
            }
        }

        fun addTimeout(node: Timeout) {
            synchronized(lock) {
                XLog.i("scheduleTimeout--->$node")
                var index = timeoutList.size
                node.addQueueTime = SystemClock.uptimeMillis()
                for (i in timeoutList.indices) {
                    if (timeoutList[i].addQueueTime + timeoutList[i].time > node.addQueueTime + node.time) {
                        index = i
                        break
                    }
                }
                timeoutList.add(index, node)
                if (index == 0) {
                    lock.notify()
                }
//            Log.i(TAG,"排序--->")
//            timeoutList.forEach { i -> Log.i(TAG,"排序后的--->$i") }
//            Log.i(TAG,"排序--->完成")
            }
        }

        private fun awaitTimeout(): Timeout? {
            synchronized(lock) {
                var node: Timeout? = null
                if (timeoutList.isEmpty()) {
                    //没有元素wait一段时间
//                    XLog.i("没有元素wait一段时间--->")
                    lock.wait(15 * TimeUnit.SECOND)
                    return null
                }
                val now = SystemClock.uptimeMillis()
                node = timeoutList.first()
                if (now - node.addQueueTime < node.time) {
                    val t = now - node.addQueueTime
                    node.updateTime = node.time - t
//                    XLog.i("元素还未到超时，wait一段时间--->${node.updateTime}")
                    lock.wait(node.updateTime)
                    return null
                }
                timeoutList.remove(node)
                return node
            }
        }
    }
}
